
// changed 06.02.05 the wafer counter is count-up from 0 to specified number 
//                  of wafers instead of count-down

#include "hardware.h"
#include "sys.h"
#include "flags.h"
#include "lcd.h"
#include "utils.h"
#include "menu.h"
#include "keycodes.h"
#include "par.h"
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <stdlib.h>
#include <stdio.h>

static BYTE OutBit;          // Current number of output (for manual)
static BYTE OptBit=0;

// Stored parameters
BYTE e_OutBit EEMEM = 0;
WORD e_PIN EEMEM    = 1234;    // PIN-code
/*
----------------
^^ F=45   R=1850
NN/NN     :12345
----------------
*/

BYTE PinCheck(void);

void MI_Opr(BYTE K);
void MI_Mot(BYTE K);
void MI_Out(BYTE K);
void MI_Inp(BYTE K);
void MI_Cou(BYTE K);
void MI_Tco(BYTE K);
void MI_Err(BYTE K);
void MI_Num(BYTE K);
void MI_Thk(BYTE K);
void MI_Pau(BYTE K);
void MI_Spd(BYTE K);
void MI_Cnt(BYTE K);
void MI_Idn(BYTE K);
void MI_Cpn(BYTE K);
void MI_Opt(BYTE K);
void MI_Scw(BYTE K);
void MI_Jmp(BYTE K);

//void EntPar(BYTE K);
void I_Inp(void);
void I_Mot(void);
void I_Opr(void);

// Menu captions
FSTR mc_Opr[]  = "*";                            //"Operate";
FSTR mc_Num[]  = {75,111,187,45,179,111,0};      //"Number";
FSTR mc_Thk[]  = {172,97,180,0};                 //"Thickn";
FSTR mc_Cou[]  = {67,192,101,191,192,184,186,0}; //"Count";
FSTR mc_Jmp[]  = {168,111,227,97,192,97,0};      //"Jump";

FSTR mc_Mot[]  = "Motor";
FSTR mc_Out[]  = "Output";
FSTR mc_Inp[]  = "Input";
FSTR mc_Err[]  = "E:";
FSTR mc_Spd[]  = "Speed";
FSTR mc_Cnt[]  = "Counter";
FSTR mc_Scw[]  = "Screw";
FSTR mc_Tco[]  = "Total counter";
FSTR mc_Idn[]  = ": ";
FSTR mc_Cpn[]  = "Change PIN";
FSTR mc_Opt[]  = "Options";

// Menu structure
//                        Prev     Next      Esc    Enter  Func     Idle  Capt  
// Main
struct Item mi_Opr  = {   NULL, &mi_Num,    NULL,    NULL, MI_Opr, I_Opr, mc_Opr};
struct Item mi_Num  = {&mi_Opr, &mi_Thk, &mi_Opr,    NULL, MI_Num,  NULL, mc_Num};
struct Item mi_Thk  = {&mi_Num, &mi_Cou, &mi_Opr,    NULL, MI_Thk,  NULL, mc_Thk};
struct Item mi_Cou  = {&mi_Thk, &mi_Jmp, &mi_Opr,    NULL, MI_Cou,  NULL, mc_Cou};
struct Item mi_Jmp  = {&mi_Cou,    NULL, &mi_Opr,    NULL, MI_Jmp,  NULL, mc_Jmp};
// Checkout
struct Item mi_Opt  = {   NULL, &mi_Out,    NULL,    NULL, MI_Opt,  NULL, mc_Opt};
struct Item mi_Out  = {&mi_Opt, &mi_Inp,    NULL,    NULL, MI_Out,  NULL, mc_Out};
struct Item mi_Inp  = {&mi_Out, &mi_Mot,    NULL,    NULL, MI_Inp, I_Inp, mc_Inp};
struct Item mi_Mot  = {&mi_Inp, &mi_Err,    NULL, &mi_Spd, MI_Mot, I_Mot, mc_Mot};
struct Item mi_Err  = {&mi_Mot, &mi_Tco,    NULL,    NULL, MI_Err,  NULL, mc_Err};
struct Item mi_Tco  = {&mi_Err, &mi_Idn,    NULL,    NULL, MI_Tco,  NULL, mc_Tco};
struct Item mi_Idn  = {&mi_Tco, &mi_Cpn,    NULL,    NULL, MI_Idn,  NULL, mc_Idn};
struct Item mi_Cpn  = {&mi_Idn,    NULL,    NULL,    NULL, MI_Cpn,  NULL, mc_Cpn};
//
struct Item mi_Spd  = {&mi_Scw, &mi_Cnt, &mi_Mot,    NULL, MI_Spd, I_Mot, mc_Spd};
struct Item mi_Cnt  = {&mi_Spd, &mi_Scw, &mi_Mot,    NULL, MI_Cnt, I_Mot, mc_Cnt};
struct Item mi_Scw  = {&mi_Cnt, &mi_Spd, &mi_Mot,    NULL, MI_Scw, I_Mot, mc_Scw};

struct Item  * Curr = &mi_Opr;  // Current menu item

#define SETMOTOR OCR2=(XTAL/1024)/StepFrq-1
// Control macros
#define INP1(M) ((InpChange & (M)) && (InpPattrn & (M)))
#define INP2(M) (InpPattrn & (M))//antimiss
#define INP0(M) ((InpChange & (M)) && !(InpPattrn & (M)))
#define MOTOR   (Flags & F_Run)
#define MOTORF  (MOTOR && !(Flags & F_Back))
#define MOTORB  (MOTOR && (Flags & F_Back))
#define SPINDLE (OutMsk & (OUT_SPUP|OUT_SPDN))
#define TABLF   (OutMsk & OUT_TBLF)
#define TABLB   (OutMsk & OUT_TBLB)
#define FEED    (OutMsk & OUT_SPDN)

FSTR m_EntPin[] = "Enter PIN:";
FSTR m_EntNewPin[] = "Enter new PIN:";
FSTR m_REntPin[] = "Re-Enter PIN:";
FSTR m_PinCh[]  = "PIN changed";
FSTR m_FS[]     = "F=";

// Mode captions
char C_Stop[]      = {'#',' ',0};
char C_SpindUp[]   = {0xD9,0xD9,0};
char C_Feed[]      = {'-','>',0};
char C_Sawing[]    = {0xDA,0xDA,0};
char C_Checkout[]  = {'?','?',0};
char B1[]  = {67,191,111,190,0}; // stop
char B2[]  = "ABAP\245\261"; // break
char IdStr[]  = "V4.0";
char Err[]  = "Error";
char Spl[]  = {65,187,188,97,183,45,54,0}; // Almaz-6

char  * MT[]  = {C_Stop, C_SpindUp, C_Feed, C_Sawing, C_Checkout};

/**********************************************************/

void SetFeed(void)
{
  ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
    StepCounter = Thickness * 4;
    //StepCounter = (Thickness * 1800.0) / ScrewStep;
    //StepCounter = 100000;
  };
  
}

void SetJump(void)
{
  ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
    StepCounter = Jump*4*1000;//o0
    //StepCounter = (Jump * 300000.0) / ScrewStep;
    Flags |= F_Jump;
  };
}

void Splash(void)
{
  LCD_CLS;
  LCD_CUR(4,0);
  LCD_Type(Spl);
  LCD_CUR(6,1);
  LCD_Type(IdStr);
  LCD_CUR(16,1);
  PAUSE(2400);
}


void ShowMode(void)
{
char P1[5],P2[5],P3[12];

  if (InpPattrn & (IN_SP_DN1))
    PORTG |= 0x04;
  else
    PORTG &= ~0x04;
    
  if (InpPattrn & (IN_SP_UP))
    PORTG |= 0x08;
  else
    PORTG &= ~0x08;

  // First line:
  LCD_CUR(0,0);
  LCD_Type(MT[Mode]); // mode
  LCD_CUR(1,0);
  if(MOTORF) {
    //return;//anti trtr 
    LCD_Put('>');   
    return;
  }
  else 
    if(MOTORB) {
        //return;//anti trtr
        LCD_Put('<');
        return;
    };
  LCD_CUR(3,0);
  if(FEED)
    { // feed speed
        DWORD T=FeedSpeed();//was FeedSpeed
    
    
    sprintf(P3,"%ld mm/min",T);
    LCD_Type(m_FS);
    LCD_Type(P3);
    }
  LCD_Blank(14);
  LCD_CUR(17,0);
  if(InpPattrn & IN_SP_READY)
    LCD_Put('*');
  else
    LCD_Put(' ');
  LCD_CUR (16,0);
  if(Flags & F_Table)
    LCD_Put (' ');
  else
    LCD_Put (0xDC);
  LCD_CUR(8,0);
  if(Flags & F_Finish)
    LCD_Type(B1); // stop
  if(Flags & F_Break)
    LCD_Type(B2); // break
  // Second line:
  LCD_CUR(0,1);
  // wafers counter
  sprintf(P1,"%ld",(DWORD)WCounter);
  sprintf(P2,"%ld",Number);
  LCD_Blank(16);
  LCD_CUR(0,1);
  LCD_Type(P1);
  LCD_Put('/');
  LCD_Type(P2);
  // thickness
  sprintf(P3,"%ld",Thickness);
  LCD_CUR(8,1);
  LCD_Put('S');
  LCD_Put('=');
  LCD_Type(P3);
  // Hide cursor
  LCD_CUR(16,1);
}

void Break(void)
{
  Flags |= F_Break; // 27.03.05 +
  STOPMOTOR;
  Switch(OUT_SPUP|OUT_SPDN,OFF);
  if(InpPattrn & IN_SP_UP) 
    Mode=_Stop_;
  else 
    {
    PAUSE(200);
    Switch(OUT_SPUP,ON);
    Mode=_SpindUp_;
    }
}

void StopCycle (void)
{

    STOPMOTOR;
    Switch (OUT_SPUP | OUT_SPDN, OFF);
    Flags |= F_Finish;
    if (InpPattrn & IN_SP_UP)
        Mode = _Stop_;
    else
        {
            PAUSE (200);
            Switch (OUT_SPUP, ON);
            Mode=_SpindUp_;
        };

}


/*** Modes *********************************************************************************************************/

void M_Checkout(void)
{
  asm ("nop");
  return;
}

#define BEGIN   if((Flags & F_Input)||(Flags & F_Done)){Flags &= ~(F_Input|F_Done);
#define END     ShowMode();}

void M_Stop(void)
{


  BYTE CB = InpPattrn & IN_CAR_BACK ? 1 : 0;
  BYTE CF = InpPattrn & IN_CAR_FORW ? 1 : 0;
  BYTE SD = InpPattrn & IN_SP_DN1 ? 1 : 0;
  BYTE SU = InpPattrn & IN_SP_UP ? 1 : 0;
/*
  if(SU) 
    Switch(LED_SPUP,ON);
  else  
    Switch(LED_SPUP,OFF);
  if(SD) 
    Switch(LED_SPDN,ON);
  else 
    Switch(LED_SPDN,OFF);
*/
BEGIN

if (!(Flags & F_Power)) {
      Switch(OUT_SPDN|OUT_TBLB|OUT_TBLF, OFF);
      STOPMOTOR;
      Flags &= ~F_Jump;
      return;
}

/*
  if(INP1(IN_SP_UP)) Switch(LED_SPUP,ON);
  else if(INP0(IN_SP_UP)) Switch(LED_SPUP,OFF);
  if(INP1(IN_SP_DN1 | IN_SP_DN2)) Switch(LED_SPDN,ON);
  else if(INP0(IN_SP_DN1 | IN_SP_DN2)) Switch(LED_SPDN,OFF);
*/
  // End switches
  if(MOTOR && INP1(IN_CAR_BACK | IN_CAR_FORW)) 
    {
    OFFMOTOR; 
   
    }

  if(SPINDLE && (INP1(IN_SP_DN1 | IN_SP_UP) || INP1(S_SPUP|S_SPDN|S_STOP))) 
    Switch(OUT_SPUP|OUT_SPDN, OFF);
  else
  // Spindle
  if(INP1(S_SPUP) && !SU) Switch(OUT_SPUP,ON);
  else if(INP0(S_SPUP|S_SPDN)) 
    Switch(OUT_SPUP|OUT_SPDN,OFF);
  else if(INP1(S_SPDN) && !SD) 
    Switch(OUT_SPDN,ON);
  
  // Table
  if(TABLF)
    {
    if(INP1(S_TBLF|S_TBLB|S_STOP)) 
      Switch(OUT_TBLB|OUT_TBLF,OFF);
    }
  else
    if(TABLB)
      {
      if(INP1(S_TBLF|S_TBLB|S_STOP)) 
        Switch(OUT_TBLB|OUT_TBLF,OFF);
      }
    else
      {
      if(INP1(S_TBLF)) 
        {
        Switch(OUT_TBLB,OFF); 
        Pause(100); 
        Switch(OUT_TBLF,ON);
        }
      else 
        if(INP1(S_TBLB)) 
          {
          Switch(OUT_TBLF,OFF); 
          Pause(100); 
          Switch(OUT_TBLB,ON);
          }
      }
  // Start
  if(INP1(S_START) && (InpPattrn & IN_SP_READY)
    && !(Flags & F_Table))
    {
    WCounter = 1;
    Flags &= ~(F_Break|F_Finish);
    Curr = &mi_Opr;
    (*Curr->Fun)(0);
    if(!SU) 
      {
      Switch(OUT_SPUP,ON);
      Mode=_SpindUp_;
      }
    else
      {
      SetFeed();
      RUNMOTOR;
      Mode=_Feed_;
      }
    }
  else
    if(INP1(S_STOP)) // Stop
      {
      Switch(OUT_SPDN|OUT_TBLB|OUT_TBLF, OFF);
      STOPMOTOR;
      Flags &= ~F_Jump;
      }
  // Carriage
  if(Jump == 0)
    {
    if(MOTORB)
      {
      if(INP1(S_CARB)) 
        {
        STOPMOTOR;

        }
      }
    else
      if(MOTORF)
        {
        if(INP0(S_CARF)) STOPMOTOR;
        }
    else
      if(INP1(S_CARF) && !CF)
        {
        RUNMOTOR1;
        }
      else 
        if(INP1(S_CARB) && !CB) 
          {
          BACKMOTOR1; 

          }
    }
  else // Jump != 0
    {
    if(!MOTOR && !(Flags & F_Jump)) {
      if(INP1(S_CARF) && !CF)
        {
        SetJump();

        RUNMOTOR;
        }
      else 
        if(INP1(S_CARB) && !CB) 
          {
          SetJump();

          BACKMOTOR; 
          }
    }
    }
END
}

void M_SpindUp(void)
{
BEGIN
  if(INP0(IN_SP_READY) || (Flags & F_Table)) 
    Break();
  if(INP2(IN_SP_UP))//was INP1! antimiss
    {
    ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {//antimiss
    
    Switch(OUT_SPDN|OUT_SPUP,OFF);
    Pause(500); 
    if((Flags & F_Break) || (Flags & F_Finish))
      {
      if(Flags & F_Finish)
        {
        Switch(OUT_TBLF,OFF);
        Pause(600); 
        Switch(OUT_TBLB,ON);
        }
      Mode=_Stop_;
      }
    else
      {
      SetFeed();
      RUNMOTOR;
      Mode=_Feed_;
      }
     } //atomic
     
     }
     
    
  if(INP1(S_STOP))
    Flags |= F_Finish;
    
  if(INP1(IN_EMRRET))
    StopCycle ();

END
}

void M_Feed(void)
{
BEGIN

if(!MOTOR)
  {
    PAUSE(100);
    Switch(OUT_SPDN,ON);
    Mode=_Sawing_;
  }
else if(INP1(IN_CAR_FORW) || INP0(IN_SP_READY) || (Flags & F_Table)) 
        Break();

if(INP1(S_STOP))
  Flags |= F_Finish;  
if(INP1(IN_EMRRET))
  StopCycle ();
  
END
}

void M_Sawing(void)
{
BEGIN

  if(INP0(IN_SP_READY) || (Flags & F_Table)) 
    Break();
  else
    {
    if(INP1(S_STOP))
      Flags |= F_Finish; 
    else
      {
      
      if(INP2(IN_SP_DN1))//was INP1 antimiss
        {

        Switch(OUT_SPDN|OUT_SPUP,OFF);
        Counter++;
        if(WCounter < Number)
          WCounter++;
        else
          Flags |= F_Finish;
        PAUSE(600);
        Switch(OUT_SPUP,ON);
        Mode=_SpindUp_;
        }
      }

    if (INP1(IN_EMRRET))
        StopCycle ();
    }
END
}

void (*ModeArray[])(void) = {
  M_Stop,
  M_SpindUp,
  M_Feed,
  M_Sawing,
  M_Checkout,
  };

/*******************************************************************************************************/

/**** Menu functions ****/

void I_Mot(void)
{
  if(Flags & F_Done){
    Flags &= ~F_Done;
    LCD_CUR(8,0);
    LCD_Put('-');
    LCD_CUR(8,0);
    }
}

void MI_Mot(BYTE K)
{
switch(K){
  case 0:
    LCD_CLS;
    LCD_Type(Curr->Caption); // show name of menu item
    LCD_CUR(8,0);
    if(Flags & F_Run)
      if(Flags & F_Back)
        LCD_Put('>');
      else
        LCD_Put('<');
    else
      if(Flags & F_Off)
        LCD_Put('+');
      else
        LCD_Put('-');
    break;
  case '6':
  case '2':
    StepCounter = (K=='6') ? StepCnt : 1;
    RUNMOTOR;   
    LCD_CUR(8,0);
    LCD_Put('<');
    break;
  case '7':
    STOPMOTOR;
    LCD_CUR(8,0);
    LCD_Put('-');
    break;
  case '8':
  case '4':
    StepCounter = (K=='8') ? StepCnt : 1;
    BACKMOTOR;
    LCD_CUR(8,0);
    LCD_Put('>');
    break;
  case K_Esc:
    OFFMOTOR;
    LCD_CUR(8,0);
    LCD_Put('+');
    break;
  }
LCD_CUR(17,1); // hide cursor
}

void MI_Out(BYTE K)
{
if(K==0){
  LCD_CLS;  // clear screen
  LCD_Type(Curr->Caption); // show name of menu item
  LCD_CUR(0,1);
  Bin(SELBYTE(OutMsk,1));
  Bin(SELBYTE(OutMsk,0));
  LCD_CUR(0,1);
  }
else if(K=='6')
  OutBit++;
else if(K=='8')
  OutBit--;
OutBit &= 0x0F;
LCD_CUR(15-OutBit,1);
if(K==K_Enter || K==K_Esc){
  if(K==K_Enter){
    OutMsk ^= (1 << OutBit);
    eeprom_write_byte (&e_OutBit, OutBit);
    }
  else
    OutMsk = 0;
  LCD_CUR(0,1);
  Bin(SELBYTE(OutMsk,1));
  Bin(SELBYTE(OutMsk,0));
  LCD_CUR(15-OutBit,1);
  Output(OutMsk);
  } 
}

void MI_Opt(BYTE K)
{
if(K==0){
  LCD_CLS;  // clear screen
  LCD_Type(Curr->Caption); // show name of menu item
  LCD_CUR(0,1);
  Bin(SELBYTE(Options,1));
  Bin(SELBYTE(Options,0));
  LCD_CUR(0,1);
  }
else if(K=='6')
  OptBit++;
else if(K=='8')
  OptBit--;
OptBit &= 0x0F;
LCD_CUR(15-OptBit,1);
if(K==K_Enter){
  Options ^= (1 << OptBit);
  eeprom_write_word (&e_Options, Options);
  LCD_CUR(0,1);
  Bin(SELBYTE(Options,1));
  Bin(SELBYTE(Options,0));
  LCD_CUR(15-OptBit,1);
  } 
else if(K==K_Esc)
  {
  Curr = &mi_Opr;
  Mode=_Stop_;
  (*Curr->Fun)(0);
  }
}

// Inputs

void ShowInputs(void)
{
  LCD_CUR(0,1);
  Hex(SELBYTE(InpPattrn,1));
  Hex(SELBYTE(InpPattrn,0));
  LCD_CUR(8,1);
  Hex(SELBYTE(InpChange,1));
  Hex(SELBYTE(InpChange,0));
  LCD_CUR(16,1);
}

void MI_Inp(BYTE K)
{
if(K==0){
  LCD_CLS;
  LCD_Type(Curr->Caption); // show name of menu item
  LCD_CUR(17,1); // hide cursor
  }
ShowInputs();
}

void I_Inp(void)
{
  if(Flags & F_Input)
    {
    Flags &= ~F_Input;
    ShowInputs();
    }
}

// Error codes

void MI_Err(BYTE K)
{
if(K==0){
  LCD_CLS;
  LCD_Type(Curr->Caption);
  Hex(eeprom_read_byte (&e_Mode));
  LCD_Put('.');
  Hex(eeprom_read_byte (&e_Flags));
  LCD_CUR(0,1);
  WORD M = eeprom_read_word (&e_Output);
  Hex(SELBYTE(M,1));
  Hex(SELBYTE(M,0));
  DWORD I = eeprom_read_word (&e_Input);
  LCD_Put('.');
  Hex(SELBYTE(I,1));
  Hex(SELBYTE(I,0));
  LCD_CUR(17,1); // hide cursor
  }
}

// Enter a digital string

BYTE Read(char * Str, BYTE N, BYTE P)
{
char C=0;
BYTE i=0;
while(1)
  {
  if(KeyPressed())
    {
    C = GetChar();
    if(C>='0' && C<='9' && i<N)
      {
      Str[i++]=C;
      if(P) LCD_Put(C);
      else LCD_Put('*');
      }
    else
      if(C==K_Esc)
        {
        i=0;
        break;
        }
    else
      if(C==K_Enter)
        break;
    }
  }
  Str[i]='\0';
  return i; 
}

// Parameters

void DisplayPar(DWORD * P, BYTE E)
{
char Str[12];
LCD_CUR(0,1);
LCD_Type(Curr->Caption); // show name of parameter
LCD_Blank(16);
LCD_CUR(8,1);
if(E) // E==1: show value
  {
  LCD_Put('=');
  sprintf(Str,"%ld",*P);
  LCD_Type(Str);
  LCD_Blank(16);
  }
else // E==0: do not show value - enter new value
  LCD_Put(':');
}

BYTE GetPar(struct Parameter* P)
{
BYTE i=0;
DWORD T;
char Str[12];
DisplayPar(P->Val,0);
if(Read(Str,P->L,1))
  {
  T = atol(Str);
  if(T >= P->Min && T <= P->Max)
    {
    *(P->Val) = T;
    eeprom_write_dword (P->EVal, T);
    }
  i=1;
  }
DisplayPar(P->Val,1);
return i;
}

void MI_Spd(BYTE K)
{
if(K==0) 
  DisplayPar(&StepFrq,1);
else if(K==K_Enter)
  {
  if(GetPar(&p_StepFrq))
    {
    cli ();
    SETMOTOR;
    sei ();
    }
  }
}

/*** Main operate mode ***************************/

void I_Opr(void)
{
cli ();
if (Flags & F_1S)
  {
  Flags &= ~F_1S;
  sei ();
  ShowMode();
  }
sei ();
}

void MI_Opr(BYTE K)
{
if(K==0){
  LCD_CLS;
  LCD_Type(Curr->Caption); // show name of menu item
  ShowMode();
  }
else if(K==K_F6)
  {
  if(PinCheck())
    {
    Curr = &mi_Opt;
    Mode=_Checkout_;
    (*Curr->Fun)(0);
    }
  else
    {
    LCD_CUR(5,1);
    LCD_Type(Err);
    Pause(1500);    
    LCD_CLS;
    LCD_Type(Curr->Caption); // show name of menu item
    ShowMode();
    }
  }
else if(K==K_F1)
  {
  Curr=&mi_Cou;
  (*Curr->Fun)(0);
  }
else if(K==K_F2)
  {
  Curr=&mi_Thk;
  (*Curr->Fun)(0);
  }
else if(K==K_F3)
  {
  Curr=&mi_Jmp;
  (*Curr->Fun)(0);
  }
}

/*** Number ***/
void MI_Num(BYTE K)
{
if(K==0){
  LCD_CLS;
  DisplayPar(&Number,1);
  }
else if(K==K_Enter)
  {
  p_Number.Max = 30000 / Thickness;
  GetPar(&p_Number);
  WCounter = 0;
  }
}

/*** Jump ***/
void MI_Jmp(BYTE K)
{
if(K==0){
  LCD_CLS;
  DisplayPar(&Jump,1);
  }
else if(K==K_Enter)
  {
  GetPar(&p_Jump);
  }
}

/*** Thickness ***/
void MI_Thk(BYTE K)
{
if(K==0){
  LCD_CLS;
  DisplayPar(&Thickness,1);
  }
else if(K==K_Enter)
  {
  p_Thickness.Max = 30000 / Number;
  GetPar(&p_Thickness);
  }
}

/*** Counter ***/
void MI_Cnt(BYTE K)
{
if(K==0){
  LCD_CLS;
  DisplayPar(&StepCnt,1);
  }
else if(K==K_Enter)
  GetPar(&p_StepCnt);
}

/*** Screw step ***/
void MI_Scw(BYTE K)
{
if(K==0){
  LCD_CLS;
  DisplayPar(&ScrewStep,1);
  }
else if(K==K_Enter)
  GetPar(&p_ScrewStep);
}

/*****************************************/

// Counters

void MI_Cou(BYTE K)
{
char Str[12];
if(K==0){
  LCD_CLS;  // clear screen
  LCD_Type(Curr->Caption); // show name of menu item
  }
else if(K==K_Del) 
  {
  DWORD CTC = eeprom_read_dword (&e_TotalCnt);
  CTC += Counter;
  eeprom_write_dword (&e_TotalCnt, CTC);
  Counter = 0; // Shift+4
  }
LCD_CUR(0,1);
LCD_Blank(16);
LCD_CUR(0,1);
sprintf(Str,"%ld",Counter);
LCD_Type(Str);
LCD_CUR(17,1); // hide cursor
}

void MI_Tco(BYTE K)
{
char Str[12];
if(K==0){
  LCD_Com(0x01);  // clear screen
  LCD_Type(Curr->Caption); // show name of menu item
  }
DWORD TC = eeprom_read_dword (&e_TotalCnt) + Counter;
sprintf(Str,"%ld",TC);
LCD_CUR(0,1);
LCD_Type(Str);
LCD_Blank(16);
LCD_CUR(17,1); // hide cursor
}

void MI_Idn(BYTE K)
{
if(K==0){
  LCD_CLS;
  LCD_Type(Curr->Caption); // show name of menu item
  LCD_Type(IdStr);
  LCD_CUR(17,1); // hide cursor
  }
}

// Security

BYTE PinCheck(void)
{
  char S[5];
  LCD_CLS;
  LCD_Type(m_EntPin);
  LCD_CUR(6,1);
  if(Read(S,4,0))
    if(atoi(S)==eeprom_read_word (&e_PIN))
      return 1;
    else
      return 0;
  else
    return 0;
}

void MI_Cpn(BYTE K)
{
char S1[5], S2[5];
BYTE i;
if(K==0){
  LCD_CLS;
  LCD_Type(Curr->Caption); // show name of menu item
  LCD_CUR(17,0);
  }
if(K==K_Enter)
  {
  if(PinCheck())
    {
    LCD_CLS;
    LCD_Type(m_EntNewPin);
    LCD_CUR(6,1);
    i=Read(S1,4,0);
    LCD_CLS;
    if(i)
      {
      LCD_Type(m_REntPin);
      LCD_CUR(6,1);
      i=Read(S2,4,0);
      LCD_CLS;
      if(!strcmp(S1,S2))
        {
        eeprom_write_word (&e_PIN, atoi(S1));
        LCD_Type(m_PinCh);
        LCD_CUR(17,1);
        return;
        }
      }
    } 
    LCD_CUR(6,1);
    LCD_Type(Err);
    LCD_CUR(17,1);
  }
}

// Init variables

void VarInit(void)
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    OutBit    = eeprom_read_byte (&e_OutBit);
    StepFrq   = eeprom_read_dword (&e_StepFrq);
    StepCnt   = eeprom_read_dword (&e_StepCnt);
    Counter   = eeprom_read_dword (&e_Counter);
    Thickness = eeprom_read_dword (&e_Thickness);
    Number    = eeprom_read_dword (&e_Number);
    Flags     = F_Off;
    Options   = eeprom_read_word (&e_Options);
    ScrewStep = eeprom_read_dword (&e_ScrewStep);
    Jump      = eeprom_read_dword (&e_Jump);
    SETMOTOR;
  };
}

// Key processing

void KeyProcess(void)
{
if(KeyPressed())
  {
  char K = GetChar();
  switch(K)
    {
    case K_Esc:   
      if (Curr->Esc) {Curr=Curr->Esc; (*Curr->Fun)(0);}
      else (*Curr->Fun)(K);
      break;
    case K_Enter: 
      if (Curr->Ent) {Curr=Curr->Ent; (*Curr->Fun)(0);}
      else (*Curr->Fun)(K);
      break;
    case '3':     
      if (Curr->Prv) {Curr=Curr->Prv; (*Curr->Fun)(0);}
      else (*Curr->Fun)(K);
      break;
    case '0':     
      if (Curr->Nxt) {Curr=Curr->Nxt; (*Curr->Fun)(0);}
      else (*Curr->Fun)(K);
      break;
    default:      
      (*Curr->Fun)(K);
    } // switch
  } // if
}
